home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
- From: daveb@geac.UUCP (David Collier-Brown)
- Newsgroups: comp.sources.misc
- Subject: v04i018: Give -- a "secure" cat program
- Message-ID: <3143@geac.UUCP>
- Date: 8 Aug 88 12:22:04 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: daveb@geac.UUCP (David Collier-Brown)
- Organization: GEAC Computers, Toronto, CANADA
- Lines: 592
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 18
- Submitted-by: "David Collier-Brown" <daveb@geac.UUCP>
- Archive-name: give
-
- Give is a program to give copies of files to ONLY persons on a
- list. It used to be available on some v6/PWB sites where competing
- groups were playing dirty tricks on each other. It may be of some
- use in a student or paranoid commercial environment.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README give.c Makefile give.1
- # Wrapped by daveb@geac on Wed Jul 20 14:15:35 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(268 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- X This is a reproduction of a v6 utility, for people who wish to
- Xlive in a paranoid universe.
- X
- X It was written in the V7/Sys V style on a Berkeley 4.2 Vax (DEC
- XULTRIX), and is expected to be portable to any Unix machine with a
- Xdatabase utility resembling dbx(3).
- END_OF_README
- if test 268 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f give.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"give.c\"
- else
- echo shar: Extracting \"give.c\" \(7990 characters\)
- sed "s/^X//" >give.c <<'END_OF_give.c'
- X/*
- X * give -- a paranoid's cat program
- X */
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <fcntl.h>
- X#include <sys/param.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#ifdef DEBUG
- X#define INSTANTIATE"
- X#endif
- X#include "debug.h"
- X
- X#define PR (void) fprintf(stderr,
- X#define EQ(a,b) strcmp(a,b) == 0
- X#define ERR (-1)
- X#define EOS '\0'
- X#define YES 1 /* Function returns. */
- X#define NO 0
- X#define OK 0 /* Program exit codes */
- X#define BAD 1
- X#define AWFULL 3
- X
- Xtypedef struct {
- X char *dptr;
- X int dsize;
- X} DATUM;
- X
- Xchar *ProgName = NULL;
- Xusage() {
- X PR "Usage: %s [person] file...\n",ProgName);
- X}
- X
- X
- Xmain(argc,argv) int argc; char *argv[]; {
- X void give(), take(), remove(), exit();
- X
- X begin("main");
- X ProgName = argv[0];
- X if (argc < 2) {
- X if (exists(".give.dir")) {
- X /* Say what we've got. */
- X printDB();
- X }
- X else {
- X /* Tell the user the usage. */
- X usage();
- X exit(BAD);
- X }
- X }
- X else if (argv[1][0] == '-') {
- X switch (toupper(argv[1][1])) {
- X case 'D': /* Its the owner doing cleanup. */
- X remove(argc-2,(char **)&argv[2]);
- X break;
- X case 'T': /* Force it to "take". */
- X take(argc-2,(char **)&argv[2]);
- X break;
- X default: /* Error in usage. */
- X usage();
- X exit(BAD);
- X }
- X }
- X else if (ownerIsRunningMe()) {
- X /* Its a give-to-someone (nonsetuid) request. */
- X give(argc-1,(char **)&argv[1]);
- X }
- X else {
- X /* Its a setuid-owner cat request. */
- X take(argc-1,(char **)&argv[1]);
- X
- X }
- X end();
- X exit(OK);
- X}
- X
- X/*
- X * take -- cat the file, if both it and the user match up
- X */
- X void
- Xtake(count, arg) int count; char *arg[]; {
- X int i;
- X char *userName, *getUserId();
- X char *path, *absPath();
- X
- X begin("take");
- X /* Find the caller's userid. */
- X userName = getUserId();
- X pr1("I am %s\n",userName);
- X pr1("count is %d\n",count);
- X
- X for (i=0; i < count; i++) {
- X /* Read the database, and see if we get a match. */
- X if ((path= absPath(arg[i])) == NULL) {
- X PR "%s: could not get the absolute path of \"%s\",",
- X ProgName,arg[i]);
- X PR " is it elsewhere or does it contains a ..?\n");
- X continue;
- X }
- X if (searchDB(userName,path)) {
- X cat(path);
- X }
- X }
- X end();
- X}
- X
- X
- X/*
- X * give -- put the person and file in the .give database
- X */
- X void
- Xgive(count, arg) int count; char *arg[]; {
- X int i;
- X char *absPath();
- X char *userName;
- X char *path;
- X
- X begin("give");
- X /* Break the user name out of the args vector. */
- X userName = arg[0];
- X count--;
- X arg = (char **)&arg[1];
- X
- X /* Find if the named person has a userid. */
- X if (validateUserId(userName) == 0) {
- X PR "%s: %s is not a known user-id on this system\n",
- X ProgName, userName);
- X exit(BAD);
- X }
- X
- X /* And process each of the files in order. */
- X for (i=0; i < count; i++) {
- X /* Find the absolute pathname of the file. */
- X if ((path= absPath(arg[i])) == NULL) {
- X PR "%s: file \"%s\" not found, ignored.\n",
- X ProgName, arg[i]);
- X }
- X else {
- X /* Put them in the database. */
- X addDB(userName,path);
- X }
- X }
- X end();
- X}
- X
- X/*
- X * remove -- remove a person-filename pair from the database
- X */
- X void
- Xremove(count, arg) int count; char **arg; {
- X int i;
- X char *absPath();
- X char *userName;
- X char *path;
- X
- X begin("give");
- X /* Break the user name out of the args vector. */
- X userName = arg[0];
- X count--;
- X arg = (char **)&arg[1];
- X
- X /* And remove each of the files in order. */
- X for (i=0; i < count; i++) {
- X /* Find the absolute pathname of the file. */
- X if ((path= absPath(arg[i])) == NULL) {
- X PR "%s: file \"%s\" not found, ignored.\n",
- X ProgName, arg[i]);
- X }
- X else {
- X /* Take them out of the database. */
- X removeDB(userName,path);
- X }
- X }
- X end();
- X}
- X
- X
- X/*
- X** Filesystem functions
- X**
- X*/
- X
- X/*
- X * absPath -- find the absolute pathname of a file, return NULL
- X * if it doesn't have (a canonical and unique) one.
- X */
- X char *
- XabsPath(name) char *name; {
- X static char path[MAXPATHLEN*2];
- X char *getcwd(), *strcat(), *strcpy();
- X
- X begin("abspath");
- X if (*name == '/') {
- X /* Its an absolute path. */
- X (void) strcpy(path,name);
- X }
- X else {
- X /* Its a relative path: prefix the working directory. */
- X if (getcwd(path,MAXPATHLEN) == NULL) {
- X PR "%s: can't find working directory, halting\n",
- X ProgName);
- X exit(AWFULL);
- X }
- X (void) strcat(strcat(path,"/"),name);
- X }
- X if (!canonical(path)) {
- X ret(NULL);
- X }
- X else if (exists(path) == NO) {
- X ret(NULL);
- X }
- X else {
- X ret(path);
- X }
- X}
- X
- X/*
- X * canonical -- test a pathname for a ".." sequence.
- X */
- X int
- Xcanonical(name) char *name; {
- X char *p, *strchr();
- X
- X begin("canonical");
- X p = name;
- X while ((p=strchr(p+1,'.')) != NULL) {
- X if (p[1] == '.') {
- X ret(NO);
- X }
- X }
- X ret(YES);
- X}
- X
- X/*
- X * exists -- stat a file for presence/absence
- X */
- X int
- Xexists(path) char *path; {
- X struct stat buf;
- X
- X return (stat(path, &buf) != ERR);
- X}
- X
- X
- X/*
- X** userid functions
- X**
- X*/
- X
- X/*
- X * getUserId -- Find the user's userid.
- X */
- X char *
- XgetUserId() {
- X struct passwd *p, *getpwuid();
- X unsigned short getuid();
- X
- X begin("getUserId");
- X if ((p=getpwuid((int)getuid())) == NULL) {
- X ret(NULL);
- X }
- X else {
- X ret(p->pw_name);
- X }
- X}
- X
- X/*
- X * validateUserId -- Find if the named person has a userid.
- X */
- X int
- XvalidateUserId(name) char *name; {
- X struct passwd *getpwnam();
- X
- X return (getpwnam(name) != NULL);
- X}
- X
- X/*
- X * ownerIsRunningMe -- return YES if the owner of the program is running it
- X */
- X int
- XownerIsRunningMe() {
- X unsigned short getuid(), geteuid();
- X
- X return (getuid() == geteuid());
- X}
- X
- X
- X
- X/*
- X** database functions -- these happen to use dbm(3x), but anything is
- X** acceptable that can provide the primitives. Ingres would be
- X** somewhat nicer...
- X*/
- X#define MAXNAME 100
- X
- X/*
- X * addDB -- add a person-filename pair.
- X */
- XaddDB(person,file) char *person, *file; {
- X DATUM key,
- X content;
- X char record[MAXNAME+MAXPATHLEN],
- X *strcat(), *strcpy();
- X
- X begin("addDB");
- X initDB();
- X key.dptr = strcat(strcat(strcpy(record,person)," "),file);
- X key.dsize = strlen(record)+1;
- X content.dptr = " ";
- X content.dsize = 2;
- X pr1("key is '%s'\n",record);
- X if (store(key,content) < 0) {
- X PR "%s: database failed on a store, halting\n",
- X ProgName);
- X exit(AWFULL);
- X }
- X end();
- X}
- X
- X/*
- X * searchDB -- see if a person-filename pair is present.
- X */
- X int
- XsearchDB(person,file) char *person, *file; {
- X DATUM key, content, fetch();
- X char record[MAXNAME+MAXPATHLEN],
- X *strcat(), *strcpy();
- X
- X begin("searchDB");
- X initDB();
- X key.dptr = strcat(strcat(strcpy(record,person)," "),file);
- X key.dsize = strlen(record)+1;
- X pr1("key is '%s'\n",record);
- X content = fetch(key);
- X pr2("content = '%s' (0x%X)\n",content.dptr,content.dptr);
- X ret(content.dptr != NULL);
- X}
- X
- X/*
- X * removeDB -- remove a person-filename pair
- X */
- XremoveDB(person,file) char *person, *file; {
- X DATUM key;
- X char record[MAXNAME+MAXPATHLEN],
- X *strcat(), *strcpy();
- X int rc;
- X
- X begin("removeDB");
- X initDB();
- X key.dptr = strcat(strcat(strcpy(record,person)," "),file);
- X key.dsize = strlen(record)+1;
- X pr1("key is '%s'\n",record);
- X rc = delete(key);
- X pr1("rc = %d\n",rc);
- X if (rc < 0) {
- X PR "%s: could not remove \"%s\" from database\n",
- X ProgName,record);
- X exit(AWFULL);
- X }
- X end();
- X}
- X
- X/*
- X * printDB -- print all person-filename pairs in the database
- X */
- XprintDB() {
- X DATUM key, firstkey(), nextkey();
- X
- X begin("printDB");
- X initDB();
- X key = firstkey();
- X if (key.dptr == NULL) {
- X usage();
- X }
- X else {
- X for (; key.dptr != NULL; key=nextkey(key))
- X (void) printf("%s\n",key.dptr);
- X }
- X end();
- X}
- X
- X/*
- X * initDB -- open the db file
- X */
- X static
- XinitDB() {
- X static openRqd = YES;
- X
- X begin("initDB");
- X if (openRqd) {
- X if (exists(".give.pag") == NO) {
- X (void) creat(".give.dir",0755);
- X (void) creat(".give.pag",0755);
- X /* Success test is the dbminit... */
- X }
- X if (dbminit(".give") < 0) {
- X PR "%s: cannot open .give.[dir|pag] file, halting\n",
- X ProgName);
- X exit(AWFULL);
- X }
- X }
- X openRqd = NO;
- X end();
- X}
- X
- X/*
- X * cat -- send a file to stdout.
- X */
- X#define BLOCKSIZE 1024
- Xcat(p) char *p; {
- X char block[BLOCKSIZE];
- X int fd,
- X i;
- X
- X begin("cat");
- X pr1("p is '%s'\n",p);
- X if ((fd=open(p,O_RDONLY)) == ERR) {
- X PR "%s: can't open %s (inpossible!)\n",
- X ProgName, p);
- X exit(AWFULL);
- X }
- X while ((i=read(fd,block,(unsigned)BLOCKSIZE)) != 0)
- X (void) write(1,block,(unsigned)i);
- X (void) close(fd);
- X}
- END_OF_give.c
- if test 7990 -ne `wc -c <give.c`; then
- echo shar: \"give.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f Makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- echo shar: Extracting \"Makefile\" \(830 characters\)
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X#
- X# give -- half of the v6 give-and-take package
- X#
- X# BINDIR is where to put the executable.
- X# MANDIR is where the manual pages go, and MANEXT is the extension.
- X# for the man pages, e.g., give.1 or give.l or give.m.
- X
- XBINDIR = /usr/local
- XMANDIR = /usr/man/manl
- XMANEXT = l
- X
- X# These should all just be right if the above ones are.
- XDIRNAME = $(BINDIR)/give
- XDIRNAME_M = $(MANDIR)/give.$(MANEXT)
- XLDFLAGS = -ldbm
- XCFLAGS = -Y
- X
- Xgive: give.c
- X $(CC) $(CFLAGS) -o give give.c $(LDFLAGS)
- X
- X$(DIRNAME_M): give.1
- X cp give.1 $(DIRNAME_M)
- X chmod 644 $(DIRNAME_M)
- X
- X$(DIRNAME): give
- X install -c -m 755 give $(DIRNAME)
- X
- Xinstall: $(DIRNAME_M) # $(DIRNAME)
- X
- Xuse:
- X cp $(DIRNAME) ./give
- X chmod 4711 give
- X
- X
- X
- Xlint:
- X lint $(CFLAGS) give.c
- Xtags:
- X ctags -w give.c
- Xgive.shar:
- X shar README give.c Makefile give.1 > give.shar
- Xclean:
- X rm -f a.out core *.o give
- END_OF_Makefile
- if test 830 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f give.1 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"give.1\"
- else
- echo shar: Extracting \"give.1\" \(1339 characters\)
- sed "s/^X//" >give.1 <<'END_OF_give.1'
- X.TH GIVE 1,local
- X.SH NAME
- Xgive \- a paranoid's copy program
- X.SH SYNOPSIS
- Xgive [person] file...
- X.br
- Xgive -d person file...
- X
- X.SH DESCRIPTION
- XGive is a program which will "cat" a particular file to a particular
- Xperson, and only that person. When it is called by its owner with a
- Xperson's userid and one or more filenames, it remembers the
- Xuser-filename pairs. When it called by someone other than the owner
- Xwith one or more filenames, it sees if the person is authorized to
- Xbe given the file(s), and if so sends a copy to stdout.
- X.PP
- XIf the command is given by itself, it will print the current
- Xcontents of the .give file(s) and/or a usage message.
- X.PP
- XIf it is given with the "-d" option, it will delete the person-file
- Xpair from the database.
- X
- X.SH EXAMPLE
- Xdave> give drew precious_file
- X.sp
- Xdrew> cd ~dave
- X.br
- Xdrew> give precious_file >$HOME/my_copy
- X.br
- Xor
- X.br
- Xdrew> ~dave/give ~dave/precious_file >my_copy
- X
- X.SH FILES
- X ./.give* the list of people and files.
- X
- X.SH HISTORY
- XThis is a rather old idea, dating from v6's give and take. If we had
- XACLs (access control lists), it would also be a useless one.
- X
- X.SH BUGS
- XThe right copy of "give" has to be executed, which tends to mean you
- Xhave to be in the same directory as the files to be given or refer
- Xto "give" by an absolute pathname.
- X.PP
- XIt was written by Dave C-B. Need I say more?
- END_OF_give.1
- if test 1339 -ne `wc -c <give.1`; then
- echo shar: \"give.1\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
- --
- David Collier-Brown. |{yunexus,utgpu}!geac!daveb
- Geac Computers Ltd., | Computer science loses its
- 350 Steelcase Road, | memory, if not its mind,
- Markham, Ontario. | every six months.
-